/*******************************************************************/
/* @ All Rights Reserved Copyright (C) 2014 broada,Co.,Ltd.        */
/*                                                                 */
/*  NAME      = frstr.c                                            */
/*  NOTE      =                                                    */
/*  DATE      = 2014/09/30 by yaohl                                */
/*******************************************************************/
#include <stdio.h>
#include <string.h>

#include "frmem.h"
#include "frstr.h"

#define STRING_MAX_ENLARGE       2048
/* 100M */
#define STRING_MAX               104857600
/*******************************************************************************
*  FUNC     :  frstr初始化
*  ARGS     :  ui_size (数据长度)
*  RTN      :  Frstr*  (normal)
*              NULL    (error)
*  NOTE     :
*******************************************************************************/
Frstr* frstr_new(unsigned int ui_size)
{
    Frstr *p_frstr = NULL;
    unsigned int ui_allocated_len = 0;
    char *p_str = NULL;

    p_frstr = frmalloc(sizeof(Frstr));
    if(p_frstr == NULL)
        return NULL;
    
    if (ui_size <= STRING_MAX_ENLARGE)
        ui_allocated_len = ui_size * 2+1;
    else
        ui_allocated_len = ui_size+1;

    p_str = frmalloc(ui_allocated_len);
    if (p_str == NULL)
    {
        frfree(p_frstr);
        return NULL;
    }
    *p_str='\0';
    p_frstr->p_str = p_str;
    p_frstr->ui_len = 0;
    p_frstr->ui_allocated_size = ui_allocated_len;

    return p_frstr;
}

/*******************************************************************************
*  FUNC     :  追加数据到frstr
*  ARGS     :  *p_frstr         (Frstr)
            :  *p_append_val    (数据)
            :  ui_append_size  (数据长度)
*  RTN      :  0       (normal)
*              1       (error)
*              2       (内存过大)
*  NOTE     :
*******************************************************************************/
int  frstr_append(Frstr *p_frstr, const char *p_append_val, unsigned int ui_append_size)
{
    unsigned int ui_allocated_len = 0;
    unsigned int ui_new_len = 0;
    char *p_new_str = NULL;

    // 数据长度 > 100M报警告
    if(ui_append_size > 104857600)
        printf("[%s(%s:%u)] size=%u (input parameter err?)\n", __func__,__FILE__,__LINE__, ui_append_size);

    ui_new_len = p_frstr->ui_len + ui_append_size;
    /* 内存空间不足时，先重新分配内存，再追加数据 */
    if (ui_new_len >= p_frstr->ui_allocated_size)
    {
        if (ui_new_len <= STRING_MAX_ENLARGE)
            ui_allocated_len = ui_new_len * 2 + 1;
        else if(ui_new_len < STRING_MAX)
            ui_allocated_len = ui_new_len + STRING_MAX_ENLARGE + 1;
        else
            return 2;

        p_new_str = frmalloc(ui_allocated_len);
        if (p_new_str == NULL)
            return 1;

        memcpy(p_new_str, p_frstr->p_str, p_frstr->ui_len);
        memcpy(p_new_str + p_frstr->ui_len, p_append_val, ui_append_size);
        p_new_str[p_frstr->ui_len + ui_append_size] = '\0';
        frfree((void *)(p_frstr->p_str));

        /* update string */
        p_frstr->p_str = p_new_str;
        p_frstr->ui_len = ui_new_len;
        p_frstr->ui_allocated_size = ui_allocated_len;
    }
    /* 追加数据 */
    else
    {
        memcpy(p_frstr->p_str + p_frstr->ui_len, p_append_val, ui_append_size);
        p_frstr->ui_len = ui_new_len;
        p_frstr->p_str[ui_new_len] = '\0';
    }

    return 0;
}

/*******************************************************************************
*  FUNC     :  截断frstr里数据
*  ARGS     :  *p_frstr (Frstr)
            :  ui_len   (数据的剩余长度)
*  RTN      :  0        (normal)
*              1        (error)
*  NOTE     :
*******************************************************************************/
void frstr_trunc(Frstr *p_frstr, unsigned int ui_len)
{
    if (p_frstr == NULL
     || p_frstr->ui_len <= ui_len
     || ui_len >= p_frstr->ui_allocated_size)
    {
        return;
    }

    p_frstr->p_str[ui_len] = '\0';
    p_frstr->ui_len = ui_len;

    return;
}

/*******************************************************************************
*  FUNC     :  释放frstr
*  ARGS     :  **pp_frstr (Frstr)
*  NOTE     :
*******************************************************************************/
void frstr_free(Frstr **pp_frstr)
{
    if (pp_frstr == NULL || *pp_frstr == NULL)
        return;

    frfree((*pp_frstr)->p_str);
    frfree(*pp_frstr);
    *pp_frstr = NULL;

    return;
}

/*******************************************************************************
*  FUNC     :  释放frstr(但不释放使用内存p_str)
*  ARGS     :  **pp_frstr (Frstr)
*  NOTE     :
*******************************************************************************/
char *frstr_free2(Frstr **pp_frstr)
{
    char *p_ret_data=NULL;
    if (pp_frstr == NULL || *pp_frstr == NULL)
        return NULL;
    p_ret_data = (*pp_frstr)->p_str;
    frfree(*pp_frstr);
    *pp_frstr = NULL;

    return p_ret_data;
}

/*******************************************************************************
*  FUNC     :  获取内存空间大小
*  ARGS     :  *p_frstr (Frstr)
*  NOTE     :
*******************************************************************************/
//unsigned int frstr_size(Frstr *p_frstr)
//{
//    if(p_frstr == NULL)
//        return 0;
//
//    return p_frstr->ui_allocated_size;
//}
